﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Util.ImageProcess;
using System.IO;
using Util;
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Threading;
using YLServerInterface.UserControls;
using BusinessClass.StateMachine;
using BusinessClass.StateMachine.Core.Types;
using BusinessClass.StateMachine.Core;
using BusinessClass.JsonClass;

namespace BusinessClass
{

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

        public string WorkingDir { get; set; }

        public string processFilePath { get; set; }
        public string ttfPath { get; set; }

        public MainWindow(string workingDir)
        {
            InitializeComponent();
            WorkingDir = workingDir;

            txtSaveDir.Text = WorkingDir;
        }
        IEnumerable<CutResult> callCuttersCut()
        {
            foreach (ImageCutter cutter in wPnlCutterContainer.Items)
            {
                var ret = cutter.Cut();
                if (ret != null)
                    yield return ret;
            }
        }

        void updateLogCut(LogJson log, IEnumerable<CutResult> newcuts)
        {
            if (log.Cut.Length == 0)
            {
                log.Cut = newcuts.ToArray();
            }
            foreach (var newcut in newcuts)
            {
                for (int i = 0; i < log.Cut.Length; i++)
                {
                    if (log.Cut[i].FileName == newcut.FileName)
                    {
                        log.Cut[i] = newcut;
                    }
                }
            }
        }
        /// <summary>
        /// 生成按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            //System.Diagnostics.Debugger.Launch();
            LogHelper logHelper = new LogHelper(WorkingDir);
            logInfo.TemplateName = cbTemplates.SelectedValue.ToString();
            updateLogCut(logInfo, callCuttersCut());
            logHelper.Log(logInfo);

            var configTxt = txtConfig.Text;// File.ReadAllText(Common.conbindPath(mobanDir, "config.json"));
            #region 从界面获取最新配置值,完善配置文件对象信息
            dynamic config = JsonConvert.DeserializeObject(configTxt);
            var lines = txtInfo.Text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries)
                .Select(str => str.Trim()).ToArray();
            for (int i = 0; i < lines.Length; i++)
            {
                var nk = lines[i].Split('：');
                for (int j = 0; j < config.rules.Count; j++)
                {
                    if (config.rules[j].name == nk[0])
                        config.rules[j].input = nk[1];
                }
            }

            var offsetx = Convert.ToSingle(txtOffsetX.Text);
            var offsety = Convert.ToSingle(txtOffsetY.Text);
            #endregion
            ttfPath = Common.conbindPath(@"C:\Windows\Fonts", (string)config.ttf);
            Machine worker = new Machine(WorkingDir, ttfPath);

            IEnumerable<string> tempFiles = new List<string>();
            prepareWorkDir();

            #region 生成状态点
            List<MakePicState> makePics = new List<MakePicState>();
            MakeFileState makeUrlTxtState = null;
            foreach (var rule in config.rules)
            {
                if (((string)rule.type).ToLower() == "png")
                {
                    makePics.Add(new MakePicState(rule, (string)config.hint));
                }
                else
                {
                    makeUrlTxtState = new MakeFileState(rule);
                }
            }
            var makePicsStateParallel = StateFactory.CreateParallelStates(makePics.ToArray());
            #endregion
            #region 打包状态点
            ActionSate<IEnumerable<String>> movePrepareFiles = new ActionSate<IEnumerable<string>>(() =>
            {
                var mobanDir = Common.conbindPath(Properties.Settings.Default.MobansDir, cbTemplates.SelectedValue.ToString());
                var dirTool = Properties.Settings.Default.ToolDir;
                var prepareFiles = FileHelper.MoveDirFiles(dirTool, WorkingDir);//移动共有文件
                var prepareFiles2 = FileHelper.MoveDirFiles(mobanDir, WorkingDir);//移动模板特有文件
                return prepareFiles.Concat(prepareFiles2);
            });
            var packageState = new PackageState(WorkingDir, "finish");
            var changeExeName = new ActionSate<Unit>(() =>
            {
                string xl = "";
                string xn = "";
                foreach (var line in lines)
                {
                    if (line.StartsWith("新郎"))
                    {
                        xl = line.Split('：')[1];
                    }
                    else if (line.StartsWith("新娘"))
                    {
                        xn = line.Split('：')[1];
                    }
                }
                rename(Common.conbindPath(WorkingDir, "finish.exe"), string.Format("{0}♥{1}婚礼邀请.exe", xl, xn));
                return new Unit();
            });

            var buildExeState = movePrepareFiles
                .ContinueWithState(files => tempFiles = tempFiles.Concat(files), packageState)
                .ContinueWithState(changeExeName);
            #endregion


            var makedFiles = worker.Visit(makePicsStateParallel).SelectMany(v => v);
            tempFiles = makedFiles;

            worker.Visit(makeUrlTxtState);
            worker.Visit(buildExeState);
            var deleteFile = StateFactory.CreateOptionalState(!(ckDelTempFile.IsChecked ?? true), new DeleteTempFilesState(tempFiles));
            worker.Visit(deleteFile);

            txtStatus.Text = "完成";
        }
        void rename(string orgName, string newName)
        {
            orgName.NewName(newName);
        }
        private void Window_DragEnter(object sender, DragEventArgs e)
        {
        }


        /// <summary>
        /// 移动需要的文件到工作目录,返回临时文件路径集合。
        /// </summary>
        Task<IEnumerable<string>> prepareFiles()
        {
            var mobanDir = Common.conbindPath(Properties.Settings.Default.MobansDir, cbTemplates.SelectedValue.ToString());
            Task<IEnumerable<string>> task = new Task<IEnumerable<string>>(
                () =>
                {
                    var dirTool = Properties.Settings.Default.ToolDir;
                    var prepareFiles = FileHelper.MoveDirFiles(dirTool, WorkingDir);//移动共有文件
                    var prepareFiles2 = FileHelper.MoveDirFiles(mobanDir, WorkingDir);//移动模板特有文件
                    return prepareFiles.Concat(prepareFiles2);
                });
            return task;
        }

        void prepareWorkDir()
        {
            var files = Directory.GetFiles(WorkingDir, "*.exe");
            foreach (var file in files)
            {

                File.Delete(file);
            }
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            if (File.Exists(Common.conbindPath(WorkingDir, "log.json")))
            {
                var logTxt = File.ReadAllText(Common.conbindPath(WorkingDir, "log.json"));
                logInfo = JsonConvert.DeserializeObject<LogJson>(logTxt);
            }
            var ts = ConfigHelper.GetTemplatesNames();
            cbTemplates.BeginInit();
            foreach (var t in ts)
            {
                cbTemplates.Items.Add(t); //还是会触发selectionchanged事件
            }
            cbTemplates.EndInit();
            cbTemplates.SelectedValue = logInfo.TemplateName ?? cbTemplates.SelectedValue;
            whenInitiCbTemplate = false;
            changeSelection();
            if (logInfo.TemplateName != cbTemplates.SelectedValue.ToString())
            {
                logInfo = new LogJson();
            }
            txtInfo.Text = File.ReadAllText(Common
                        .conbindPath(
                        WorkingDir, "需要准备的资料.txt"));
        }
        bool whenInitiCbTemplate = true;
        private void changeSelection()
        {
            if (!whenInitiCbTemplate)
            {
                if (logInfo.TemplateName != cbTemplates.SelectedValue.ToString())
                {
                    logInfo = new LogJson();
                }
                wPnlCutterContainer.RemoveElements();
                var mobanDir = Common.conbindPath(Properties.Settings.Default.MobansDir, cbTemplates.SelectedValue.ToString());
                var txt = File.ReadAllText(Common.conbindPath(mobanDir, "config.json"));
                txtConfig.Text = txt;
                loadImgs(WorkingDir, mobanDir);
            }
        }
        private void cbTemplates_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            changeSelection();
        }

        LogJson logInfo = new LogJson();
        void loadImgs(string dir, string mobanDir)
        {

            var configTxt = File.ReadAllText(Common.conbindPath(mobanDir, "config.json"));
            dynamic config = JsonConvert.DeserializeObject(configTxt);

            var configPicFiles = getConfigPicFilePaths(mobanDir);//配置文件需要截取的图片
            var files = Directory.GetFiles(dir, "*.jpg")
                .Where(file => configPicFiles.Contains(file) == false) //不读取配置文件中定义的图片
                .OrderBy(str => str)
                .ToArray();

            for (int i = 0; i < files.Length; i++)
            {
                var savepath = "";
                int w = 0;
                int h = 0;
                CutResult cutr = null;
                if (i < config.imgs.Count)
                {
                    dynamic imgconfig = config.imgs[i];
                    savepath = Common.conbindPath(WorkingDir, (string)imgconfig.name);
                    w = (int)imgconfig.w;
                    h = (int)imgconfig.h;
                    var cuttedFile = logInfo.Cut.Where(cr => cr.FileName == Common.getFileName(savepath));
                    if (cuttedFile.Count() > 0)
                    {
                        cutr = cuttedFile.First();
                    }
                }
                ImageCutter c = new ImageCutter(files[i], savepath, w, h, cutr);
                c.Height = Convert.ToDouble(Properties.Settings.Default.ImgCutterH);

                wPnlCutterContainer.AddElement(c);
            }

        }
        private IEnumerable<string> getConfigPicFilePaths(string mobanDir)
        {
            var configTxt = File.ReadAllText(Common.conbindPath(mobanDir, "config.json"));
            dynamic config = JsonConvert.DeserializeObject(configTxt);
            foreach (var imgconfig in config.imgs)
            {
                yield return Common.conbindPath(WorkingDir, (string)imgconfig.name);
            }
        }
        private void btnSaveConfig_Click(object sender, RoutedEventArgs e)
        {
            var mobanDir = Common.conbindPath(Properties.Settings.Default.MobansDir, cbTemplates.SelectedValue.ToString());
            var path = Common.conbindPath(mobanDir, "config.json");
            File.WriteAllText(path, txtConfig.Text);
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            ConfigSetting cs = new ConfigSetting();
            cs.Show();
        }
    }
}
